package com.dao;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Hibernate;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.springframework.dao.DataAccessException;

import com.model.OrdenDeCompra;
import com.model.Remito;
import com.query.OrdenDeCompraQuery;
import com.query.ReporteRentabilidadQuery;

public class OrdenDeCompraDAOImpl extends
		BaseHibernateDAO<OrdenDeCompra, OrdenDeCompraQuery> {

	@Override
	public Class<OrdenDeCompra> getModelClass() {
		return OrdenDeCompra.class;
	}

	@Override
	public List<String> getListNames() {
		List<String> list = new ArrayList<String>();
		return list;
	}

	@Override
	public OrdenDeCompra findInitialize(Long id) throws DataAccessException {
		OrdenDeCompra unaOC = super.find(id);
		Hibernate.initialize(unaOC.getListaDetalleOrdenDeCompra());
		Hibernate.initialize(unaOC.getListaDeRemitos());

		for (Remito remito : unaOC.getListaDeRemitos()) {
			Hibernate.initialize(remito.getDetalleRemito());
		}

		return unaOC;
	}

	/**
	 * 
	 * Obtiene la Orden de compra con el número más alto
	 * 
	 */
	@SuppressWarnings("unchecked")
	@Override
	public OrdenDeCompra get(Object query) throws DataAccessException {

		OrdenDeCompra ordenDeCompra = null;

		List<OrdenDeCompra> list = null;

		DetachedCriteria criteria = DetachedCriteria
				.forClass(OrdenDeCompra.class);
		criteria.addOrder(Order.desc("numeroOrdenDeCompra"));

		list = (List<OrdenDeCompra>) getHibernateTemplate().findByCriteria(
				criteria);

		if (list.size() > 0) {
			ordenDeCompra = list.get(0);
		}

		return ordenDeCompra;
	}

	@SuppressWarnings({ "rawtypes" })
	@Override
	public List getListObjects(Object query) throws DataAccessException {

		ReporteRentabilidadQuery rrq = (ReporteRentabilidadQuery) query;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

		String queryString = "select producto.detalle as producto, familia.descripcion as familia, unidadDeMedida.descripcion, "

				// subquery para ventas
				+ " (select sum(ordenDeCompraDetalle2.precio * remitoDetalle2.cantidadRecepcionada) as venta"
				+ " from OrdenDeCompra as ordenDeCompra2"
				+ " left join ordenDeCompra2.listaDeRemitos as remito2"
				+ " left join remito2.detalleRemito as remitoDetalle2 "
				+ "	left join ordenDeCompra2.listaDetalleOrdenDeCompra as ordenDeCompraDetalle2"
				+ " left join ordenDeCompraDetalle2.producto as producto2"
				+ " left join ordenDeCompra2.proveedor as proveedor2"
				+ " left join remitoDetalle2.productoCodigo as productoCodigo2 "
				+ " left join productoCodigo2.producto as productoCodigoProducto2 "
				+ "	where proveedor2.tipoProveedor = 'I' and producto.id = producto2.id and productoCodigoProducto2.id = producto2.id"
				+ "	group by  producto2.id), "

				// subquery para compras
				+ " (select sum(ordenDeCompraDetalle3.precio * remitoDetalle3.cantidadRecepcionada) as compra"
				+ " from OrdenDeCompra as ordenDeCompra3"
				+ " left join ordenDeCompra3.listaDeRemitos as remito3"
				+ " left join remito3.detalleRemito as remitoDetalle3 "
				+ "	left join ordenDeCompra3.listaDetalleOrdenDeCompra as ordenDeCompraDetalle3"
				+ " left join ordenDeCompraDetalle3.producto as producto3"
				+ " left join ordenDeCompra3.proveedor as proveedor3"
				+ " left join remitoDetalle3.productoCodigo as productoCodigo3 "
				+ " left join productoCodigo3.producto as productoCodigoProducto3 "
				+ "	where proveedor3.tipoProveedor = 'E' and producto.id = producto3.id and productoCodigoProducto3.id = producto3.id"
				+ "	group by  producto3.id), "

				// subquery para ventas en kilos
				+ " (select sum(producto4.peso * remitoDetalle4.cantidadRecepcionada) as ventas_peso"
				+ " from OrdenDeCompra as ordenDeCompra4"
				+ " left join ordenDeCompra4.listaDeRemitos as remito4"
				+ " left join remito4.detalleRemito as remitoDetalle4 "
				+ "	left join ordenDeCompra4.listaDetalleOrdenDeCompra as ordenDeCompraDetalle4"
				+ " left join ordenDeCompraDetalle4.producto as producto4"
				+ " left join ordenDeCompra4.proveedor as proveedor4"
				+ " left join remitoDetalle4.productoCodigo as productoCodigo4 "
				+ " left join productoCodigo4.producto as productoCodigoProducto4 "
				+ "	where proveedor4.tipoProveedor = 'I' and producto.id = producto4.id and productoCodigoProducto4.id = producto4.id and producto4.peso <> null and producto4.peso > 0"
				+ "	group by  producto4.id), "
				
				// subquery para compras en kilos
				+ " (select sum(producto5.peso * remitoDetalle5.cantidadRecepcionada) as compras_peso"
				+ " from OrdenDeCompra as ordenDeCompra5"
				+ " left join ordenDeCompra5.listaDeRemitos as remito5"
				+ " left join remito5.detalleRemito as remitoDetalle5 "
				+ "	left join ordenDeCompra5.listaDetalleOrdenDeCompra as ordenDeCompraDetalle5"
				+ " left join ordenDeCompraDetalle5.producto as producto5"
				+ " left join ordenDeCompra5.proveedor as proveedor5"
				+ " left join remitoDetalle5.productoCodigo as productoCodigo5 "
				+ " left join productoCodigo5.producto as productoCodigoProducto5 "
				+ "	where proveedor5.tipoProveedor = 'E' and producto.id = producto5.id and productoCodigoProducto5.id = producto5.id and producto5.peso <> null and producto5.peso > 0"
				+ "	group by  producto5.id)"
				
				// from
				+ " from OrdenDeCompra as ordenDeCompra"
				+ " left join ordenDeCompra.listaDeRemitos as remito"
				+ " left join remito.detalleRemito remitoDetalle "
				+ "	left join ordenDeCompra.listaDetalleOrdenDeCompra as ordenDeCompraDetalle"
				+ " left join ordenDeCompraDetalle.producto as producto"
				+ " left join producto.familia as familia"
				+ " left join ordenDeCompra.proveedor as proveedor"
				+ " left join producto.unidadDeMedida as unidadDeMedida";

		boolean where = false;

		if (rrq.getFechaDesde() != null) {
			queryString = queryString
					+ " where ordenDeCompra.fechaOrdenDeCompra >=  " + "'"
					+ sdf.format(rrq.getFechaDesde()) + "'";
			where = true;
		}

		if (rrq.getFechaHasta() != null) {
			if (where) {
				queryString = queryString
						+ " and ordenDeCompra.fechaOrdenDeCompra <= " + "'"
						+ sdf.format(rrq.getFechaHasta()) + "'";
			} else {
				queryString = queryString
						+ " where ordenDeCompra.fechaOrdenDeCompra <= " + "'"
						+ sdf.format(rrq.getFechaHasta()) + "'";
				where = true;
			}
		}

		if (rrq.getFamiliaID() != null) {
			if (where) {
				queryString = queryString
						+ " and familia.id = "
						+ rrq.getFamiliaID();
			} else {
				queryString = queryString
						+ " where familia.id = "
						+ rrq.getFamiliaID();
				where = true;
			}
		}

		if (rrq.getProductoID() != null) {
			if (where) {
				queryString = queryString
						+ " and producto.id = "
						+ rrq.getProductoID();
			} else {
				queryString = queryString
						+ " where producto.id = "
						+ rrq.getProductoID();
				where = true;
			}
		}

		// group by
		queryString = queryString
				+ "	group by  producto.id, producto.detalle, familia.id, familia.descripcion, unidadDeMedida.descripcion ";

		if (rrq.getFamiliaID() != null && rrq.getProductoID() != null) {
			queryString = queryString + " having familia.id = "
					+ rrq.getFamiliaID() + " and producto.id = "
					+ rrq.getProductoID();
		} else if (rrq.getFamiliaID() != null) {
			queryString = queryString + " having familia.id = "
					+ rrq.getFamiliaID();
		} else if (rrq.getProductoID() != null) {
			queryString = queryString + " having producto.id = "
					+ rrq.getProductoID();
		}

		queryString = queryString + "	order by producto.detalle desc";

		List listaReporteRentabilidad = getHibernateTemplate()
				.find(queryString);
		return listaReporteRentabilidad;

	}
}
